/*! \file GraphFunctions.hpp */

#ifndef GRAPHFUNCTIONS_HPP_INCLUDED
#define GRAPHFUNCTIONS_HPP_INCLUDED

#include "Graph.hpp"
#include "GraphDatabase.hpp"

#include <vector>
#include <list>

#include <QXmlStreamWriter>
#include <QFile>


namespace TopologicalLearner
{
/** A class consisting of static functions for manipulation of graphs.
 * This class contains frequently used functions for the manipulation of graphs such as graph edit distance,
 * subgraph isomorphism, removal of isolated vertices etc.
*/

// Forward declarations
/*
class Graph;
class GraphDatabase;
*/


class GraphFunctions
{

private:

/**
* Saves all the graphs to a file in the gspan format.
* @param sFilename The filename to save to
* @param kVec A vector of graphs to save
*/
//void SaveGSpanData(std::string sFilename, const std::vector<Graph>& kVec);

/**
* Loads the result (frequent subgraphs) from the gSpan algorithm
* @param sFilename The filename to load from
* @return A vector of frequent subgraphs
*/
  //  std::vector<GSpanStruct> LoadGSpanData(std::string sFilename);

public:

/**
 * Saves a graph as a dot file.
 * The function saves a specified graph to file and if specified, an overlay graph may be given to visualize common vertices and edges.
 * @param sFilename A std::string of the resulting dot file.
 * @param G The graph to save to file.
 * @param pOverlay A pointer to a Graph that will be used as an overlay.
*/
static void SaveGraph(std::string sFilename, const Graph& G, const GraphDatabase* pD, const Graph* pOverlay = 0);

/**
 * Saves a graph as a dot file.
 * The function saves a specified graph to file and if specified, an overlay graph may be given to visualize common vertices and edges.
 * @param sFilename A std::string of the resulting dot file.
 * @param G The graph to save to file.
 * @param pOverlay A vector of pointers to Graph's that will be used as overlays.
*/
static void SaveGraph(std::string sFilename, const Graph& G, std::vector<const Graph*> pOverlay, const GraphDatabase* pD);


/**
 * Saves the graph without graphizwriter to have more control
 */
static void SaveGraphToFile(std::string sfilename, const Graph& g, const GraphDatabase& D);

/**
 * Saves the graph without graphizwriter to have more control
 */
static void SaveOverlayGraphToFile(std::string sfilename, const Graph& mainGraph, const Graph& inputGraph, const Graph& editedGraph, const GraphDatabase& D);

/**
 * Removes all the vertices that have no edges.
 * @param pG A pointer to the graph to remove the isolated vertices from.
*/
static void RemoveIsolatedVertices(Graph* pG);

/**
 * Finds the vertex that has a specific ID (unsigned int) and returns the vertex.
 * @param iID The ID of the vertex
 * @param G The graph to search for the vertex
*/
static std::pair< bool, Vertex >
        FindVertex(unsigned int iID, const Graph& G);

/**
 * Finds the edge that has a specific ID (unsigned int) and returns the vertex.
 * @param iID The ID of the edge
 * @param G The graph to search for the vertex
 * @return a pair, first is a boolean if the edge exists, second is the edge. If it does not exist, then the edge returned is uninitialized!
*/

std::pair<bool, Edge> FindEdge(const Vertex v1,const Vertex v2,const Graph& G);

/**
 * Gives the edit distance between G1 and G2
*/
static int EditDistance(const Graph& G1, const Graph& G2);

/**
 * Returns true/false depending on if the graphs are equal.
*/
static bool GraphEqual(const Graph& G1, const Graph& G2, bool isUnique = true);

/**
 * Removes graph duplicates and ensures that the resulting vector contains only unique graphs.
 * @param pVec A pointer to a std::vector containing the graphs.
*/
static void RemoveDuplicates(std::vector<Graph>* pVec = 0);

/**
 * Returns true if G1 is a subgraph of G2.
*/
static bool IsSubgraphContained(const Graph& G1, const Graph& G2, bool bIsUnique = true);

/**
 * Returns a pair where the first component is true if G1 is subgraph isomorphic to G2 and
 * the second component gives the mapping from G1 to G2
 * @param bAllMappings If bisUnique = false, and this is true then it returns as a second component
 * all possible mappings. Otherwise it just returns any mapping if G1 is subgraph isomorphic to G2.
*/
static std::pair<bool, std::vector< std::map<Vertex, Vertex> > >
IsSubgraphContained(const Graph& G1, const Graph& G2, bool bIsUnique, bool bAllMappingsbool);

//std::pair<vertex_descriptor,vertex_descriptor>

/**
 * Calls gSpan upon the specified vector of graphs and returns the frequent subgraphs
 * @param kVec A vector of graphs to find frequent subgraphs in
 * @param dFreq The least frequency of the frequent subgraphs
 */
//static std::vector<GSpanStruct> GSpan(const std::vector<Graph>& kVec, double dFreq);

/**
 * Returns true if the vertex sets of the two graphs have exactly iK vertices in common
 * @param iK The number of vertices the two graphs should have in common.
*/
static bool HasVertexCommon(const Graph& G1, const Graph& G2, int iK);

/**
 * Returns the induced subgraph for the vertex set V of graph G
 * @param V The vertex set to form the induced subgraph
 * @param G The graph to form the induced subgraph of
*/
static Graph InducedSubgraph(std::vector<Vertex> V, const Graph& G);

/**
 * Returns the graph union of a vector of graph.
 * @param kGraphs The vector to form a union of
*/
static Graph GraphUnion( const std::vector<Graph>& kGraphs );

/**
 * Returns the graph union of a list of graphs
*/
static Graph GraphUnion( std::list<Graph>& kGraphs );

static Graph GraphUnion( std::list<const Graph*>& kGraphs );


/**
* Given a graph decomposition, a graph database and a selection of one of the graphs
* of the decomposition, this function returns an Edit operation distribution.
* @param C A decomposition of the graph G into a set of subgraphs C, which when forming the union will make up
* the graph G.
* @param D The graph database to use for creating the probability distribution
* @param iIndex An index of the vector C, this parameter says which one of the partitions we're examining.
* @param G The complete graph to do predition on
* @param iExcludeGraph Optional parameter of the ID of a specific graph that is not be used for prediction.
* @return A discrete edit operation map over all possible edit operations.
*/
static EditOpDist GetDistribution(const std::vector< std::pair<Graph, VertexMappings > >& C,
  const GraphDatabase& D, int iIndex, const Graph& G, int iExcludeGraph = -1, bool bUnique = true);


/**
 * Applies the specified edit operation upon a graph and returns the result.
*/
static Graph ApplyEditOp(const Graph& G, EditOp vEditOp, bool bUnique = true);

static void PrintEditOp(const Graph& G, EditOp& kOp, const GraphDatabase& D);

static void PrintEditOp(const Graph& G, EditOp& kOp);

static void SaveVectorOfGraphs(const GraphDatabase& D, std::string sDir, const std::vector<Graph>& kVec, int iMax = -1);


/**
  * Save a graph to XML format that is readable by GraphLoader
  */
static bool SaveGraphToXML(std::string XMLfilename, const Graph& G, const GraphDatabase& D);


static GraphDatabase ExtractSegments(GraphDatabase& D, std::string path,
                                     CategoryDegreeDist dist, double centralNodenessThreshold, bool bGraphwise = false, int minSegmentedGraphSize = -1 );
/**
 * Calculate the cluster coefficient of each vertex in the specified graph G and return
 * this as the first component, the second component is the average cluster coefficient of the
 * complete graph.
*/
static std::pair<ClusteringMap, float> CalculateClusterCoeff(const Graph& G);

/**
 * Calculate the characteristic path length, which is the sum of the shortest path between each combination
 * of vertices in the graph, divided by the total number of combinations between pairs of vertices
 */
static std::pair<float, int> GetCharacteristicPathLengthDiameter(const Graph& G);

static int GetNumOfVerticesOfCategory(const Graph& G, std::set<std::string> sSet, const GraphDatabase& D);

static std::vector<FrequentSubgraph> GetClosedFrequentSubgraphs(const std::vector<FrequentSubgraph>& kFSGs);

};


  struct VertexLabelPredicate {
    VertexLabelPredicate(const Graph& subgraph, const Graph& graph) :
      m_subgraph(subgraph), m_graph(graph) {}

    bool operator() (Vertex v1, Vertex v2)
     {
      //const bool rvo(AtomProperty<atomic_numberS,typename Molecule::atom_type>::get(m_subgraph_mol.get_atom(v1))
     // == AtomProperty<atomic_numberS,typename Molecule::atom_type>::get(m_graph_mol.get_atom(v2)));
        int i1 = get(boost::vertex_name, m_subgraph, v1);
        int i2 = get(boost::vertex_name, m_graph, v2);
        //std::cout << "v1: " << i1 << ", v2: " << i2 << std::endl;
        return i1 == i2 ;
    }
   private :
    const Graph& m_subgraph;
    const Graph& m_graph;
  };

class trueEdgePredicate {
public:
  trueEdgePredicate() {}
  bool operator() (Edge e1, Edge e2){
    return true;
  }
};


}
#endif // GRAPHFUNCTIONS_HPP_INCLUDED
